#include <MatrixClock.h>




MatrixClock::MatrixClock(int  DIN,int  CLK,int  CS)
{
    lc= LedControl(DIN,CLK,CS,maxDevices);
}
void MatrixClock::init(){
    
    this->flag=0;
    this->row=0;
    this->lastmillis=millis();
    this->switchtime = millis();
    this->switchflag = 0;
    this->colyear = 1;
    this->count = 0;
    this->dots = 0;
    for(byte i=0;i<maxDevices;i++)
    {
        lc.shutdown(i,false);
        lc.setIntensity(i,1);
    }
}

void MatrixClock::timeinit(uint8_t hour,uint8_t minute,uint8_t second)
{
    // this->flag=0;
    // this->row=0;
    // this->lastmillis=millis();
    // this->switchtime = millis();
    // this->switchflag = 0;
    // this->colyear = 1;
    // this->count = 0;
    // for(byte i=0;i<maxDevices;i++)
    // {
    //     lc.shutdown(i,false);
    //     lc.setIntensity(i,1);
    // }
    this->lasthour =hour;
    this->lastminute =minute;
    this->lastsecond = second;
    Merge(hour,minute,second);
}

byte MatrixClock::isChanged(byte hour,byte minute,byte second)
{    
    if(hour/10 != lasthour/10)
        bitSet(flag,5); 
    if(hour%10 != lasthour %10)
        bitSet(flag,4);         
    if(minute/10 !=lastminute/10)
        bitSet(flag,3);
    if(minute %10 != lastminute %10)
        bitSet(flag,2);
    if(second / 10 != lastsecond /10)
        bitSet(flag,1);
    if(second %10 != lastsecond %10)
        bitSet(flag,0);
    
    lasthour = hour;
    lastminute = minute;
    lastsecond = second;
    return flag;
}

void MatrixClock::Merge(uint8_t hour,uint8_t minute,uint8_t second)
{
    for(int i=0;i<8;i++)
     matrix[i]=0;
  byte h1= hour/10;
  byte h2= hour%10;
  byte m1=minute/10;
  byte m2=minute%10;
  byte s1=second/10;
  byte s2=second%10;
  unsigned long temp;
  for(int i=0;i<8;i++)
  {
    temp=pgm_read_byte(&num[h1][i]);
    matrix[i]=(temp<<23)|matrix[i];      //temp有用的是高四位，
    temp = pgm_read_byte(&num[h2][i]);
    matrix[i]=(temp<<18)|matrix[i];
    temp= pgm_read_byte(& num[m1][i]);
    matrix[i]=(temp<<11)|matrix[i];
    temp=pgm_read_byte(&num[m2][i]);
    matrix[i]=(temp<<6)|matrix[i];
    temp=pgm_read_byte(&snum[s1][i]);
    matrix[i]=temp|matrix[i];
    temp=pgm_read_byte(&snum[s2][i]);
    matrix[i]= (temp>>4)|matrix[i];
  }
   matrix[1]=(1<<20)|matrix[1];
   matrix[2]=(1<<20)|matrix[2];
   matrix[4]=(1<<20)|matrix[4];
   matrix[5]=(1<<20)|matrix[5];
}

void MatrixClock::RollMerge(uint8_t hour,uint8_t minute,uint8_t second,bool updown)
{
    uint8_t temp;
    // if(millis()-this->lastmillis>=INTERVEL)
    // {      
        if(isChanged(hour,minute,second))
        {            
            if(updown)
            {
                //向0行滚动一行,即向上滚动
                for(int i=0;i<7;i++)
                {            
                    if(bitRead(flag,5))
                        for(int j=30;j>=27;j--)                    
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,4))
                        for(int j=25;j>=22;j--)
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,3))
                        for(int j=18;j>=15;j--)                    
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,2))
                        for(int j=13;j>=10;j--)                    
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,1))
                        for(int j=7;j>=5;j--)                    
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,0))
                        for(int j=3;j>=1;j--)                    
                            if(bitRead(matrix[i+1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                }            
                //处理第7行；
                if(bitRead(flag,5))
                {
                    temp=pgm_read_byte(&num[hour/10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i+23);
                        else
                            bitClear(matrix[7],i+23);
                }
                if(bitRead(flag,4))
                {
                    temp = pgm_read_byte(&num[hour%10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i+18);
                        else
                            bitClear(matrix[7],i+18);
                }
                if(bitRead(flag,3))
                {
                    temp = pgm_read_byte(&num[minute /10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i+11);
                        else
                            bitClear(matrix[7],i+11);
                }
                if(bitRead(flag,2))
                {
                    temp = pgm_read_byte(&num[minute %10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i+6);
                        else
                            bitClear(matrix[7],i+6);
                }
                if(bitRead(flag,1))
                {
                    temp = pgm_read_byte(&snum[second /10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i);
                        else
                            bitClear(matrix[7],i);
                }
                if(bitRead(flag,0))
                {
                    temp = pgm_read_byte(&snum[second % 10][row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[7],i-4);
                        else
                            bitClear(matrix[7],i-4);
                }            
            }
            else
            {
                //向下滚动，即向第7行滚动一行
                for(int i=7;i>=1;i--)
                {            
                    if(bitRead(flag,5))
                        for(int j=30;j>=27;j--)                    
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,4))
                        for(int j=25;j>=22;j--)
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,3))
                        for(int j=18;j>=15;j--)                    
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,2))
                        for(int j=13;j>=10;j--)                    
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,1))
                        for(int j=7;j>=5;j--)                    
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                    if(bitRead(flag,0))
                        for(int j=3;j>=1;j--)                    
                            if(bitRead(matrix[i-1],j))
                                bitSet(matrix[i],j);
                            else
                                bitClear(matrix[i],j);
                }
            
                //处理第0行；
                if(bitRead(flag,5))
                {
                    temp=pgm_read_byte(&num[hour/10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i+23);
                        else
                            bitClear(matrix[0],i+23);
                }
                if(bitRead(flag,4))
                {
                    temp = pgm_read_byte(&num[hour%10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i+18);
                        else
                            bitClear(matrix[0],i+18);
                }
                if(bitRead(flag,3))
                {
                    temp = pgm_read_byte(&num[minute /10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i+11);
                        else
                            bitClear(matrix[0],i+11);
                }
                if(bitRead(flag,2))
                {
                    temp = pgm_read_byte(&num[minute %10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i+6);
                        else
                            bitClear(matrix[0],i+6);
                }
                if(bitRead(flag,1))
                {
                    temp = pgm_read_byte(&snum[second /10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i);
                        else
                            bitClear(matrix[0],i);
                }
                if(bitRead(flag,0))
                {
                    temp = pgm_read_byte(&snum[second % 10][7-row]);
                    for(int i=7;i>=4;i--)
                        if(bitRead(temp,i))
                            bitSet(matrix[0],i-4);
                        else
                            bitClear(matrix[0],i-4);
                }
            }
            row++;
            if(row>7)
            {
                row=0;               
                flag=0;
            }
        }

        // this->lastmillis = millis();        
    // }
}

void MatrixClock::Display()
{
    for(int i=0;i<8;i++)
        for(int j=0;j<8;j++)
        {
        lc.setLed(3,i,j,bitRead(matrix_clock[i],31-j));
        lc.setLed(2,i,j,bitRead(matrix_clock[i],23-j));
        lc.setLed(1,i,j,bitRead(matrix_clock[i],15-j));
        lc.setLed(0,i,j,bitRead(matrix_clock[i],7-j));
        }
}

void MatrixClock::Display(unsigned int intervel)
{
    if(millis()-this->lastmillis>=intervel)
    {
        for(int i=0;i<8;i++)
            for(int j=0;j<8;j++)
            {
                this->lc.setLed(3,i,j,bitRead(matrix[i],31-j));
                this->lc.setLed(2,i,j,bitRead(matrix[i],23-j));
                this->lc.setLed(1,i,j,bitRead(matrix[i],15-j));
                this->lc.setLed(0,i,j,bitRead(matrix[i],7-j));
            }

        this->lastmillis = millis();
    }
}

void MatrixClock::testdisplay(uint16_t year,uint8_t month,uint8_t day,uint8_t dow,uint8_t hour,uint8_t minute,uint8_t second,bool updown)
{   
   

 
    if(millis()-switchtime>=INTERVEL)
    {
        

        //更新时间年月日三数组
        dayupdate(year,month,day,dow);
        RollMerge(hour,minute,second,false);

        switch(switchflag)
        {
            case 1:   //时间向年月数组切换
                if(count<3)
                {                
                    count++;

                    //清空matrix_clock数组
                    for(int i=0;i<8;i++)
                        matrix_clock[i]=0;

                    //生成matrix_clock数组
                    
                    for(int i=0;i<8;i++)
                    {
                        switch (colyear)
                        {
                            case 0:
                                matrix_clock[i] = matrix[i];
                                break;
                            case 32:
                                matrix_clock[i] =matrix_ym[i];
                                break;
                            default:
                                matrix_clock[i] |= matrix[i]<<colyear;
                                matrix_clock[i] |= matrix_ym[i]>>(32-colyear);                     
                        }

                    }
                    
                }
                else
                {
                    count=0;
                     
                    if(colyear<32)
                        colyear++;
                    else
                    {
                        colyear=1;
                        switchflag=2;
                    }
                }
                
                break;
            case 2:   //年月数组向日期数组切换
                if(count<3)
                {                
                    count++;

                    //清空matrix_clock数组
                    for(int i=0;i<8;i++)
                        matrix_clock[i]=0;

                    //生成matrix_clock数组
                    
                    for(int i=0;i<8;i++)
                    {
                        switch (colyear)
                        {
                            case 0:
                                matrix_clock[i] = matrix_ym[i];
                                break;
                            case 32:
                                matrix_clock[i] =matrix_day[i];
                                break;
                            default:
                                matrix_clock[i] |= matrix_ym[i]<<colyear;
                                matrix_clock[i] |= matrix_day[i]>>(32-colyear);                     
                        }

                    }
                    
                }
                else
                {
                    count=0;
                     
                    if(colyear<32)
                        colyear++;
                    else
                    {
                        colyear=1;
                        switchflag=0;
                    }
                }
                
                break;
            default:   //显示正常时间
             //清空matrix_clock数组
                for(int i=0;i<8;i++)
                    matrix_clock[i]=0;
                for(int i=0;i<8;i++)
                    matrix_clock[i] = matrix[i];
                
                if(count<1200)
                    count++;
                else
                {
                    count=0;
                    switchflag=1;
                }
        }

        switchtime = millis();
    }

    //显示matrix_clock数组
    // for(int i=0;i<8;i++)
    //     for(int j=0;j<8;j++)
    //     {
    //         lc.setLed(3,i,j,bitRead(matrix_clock[i],31-j));
    //         lc.setLed(2,i,j,bitRead(matrix_clock[i],23-j));
    //         lc.setLed(1,i,j,bitRead(matrix_clock[i],15-j));
    //         lc.setLed(0,i,j,bitRead(matrix_clock[i],7-j));
    //     }
    Display();
}

void MatrixClock::dayupdate(uint16_t year, uint8_t month, uint8_t day, uint8_t dow)
{
    
    unsigned long temp;
    // uint8_t y4 = year % 10;
    // year /= 10;
    // uint8_t y3 = year % 10;
    // year /= 10;
    // uint8_t y2 = year % 10;
    // uint8_t y1 = year / 10;
    uint8_t m1 = month / 10;
    uint8_t m2 =month % 10;
    uint8_t d1 = day / 10;
    uint8_t d2 = day % 10;

    //重置月份和日期
    for(int i=0;i<8;i++)
        matrix_ym[i]=0;

    //更新月份和日期，格式如：02-24
    for(int i=0;i<8;i++)
    {
        // temp = pgm_read_byte(&num[y1][i]);
        // matrix_ym[i] = (temp<< 23) | matrix_ym[i];
        // temp = pgm_read_byte(&num[y2][i]);
        // matrix_ym[i] = (temp<< 18)| matrix_ym[i];
        temp = pgm_read_byte(&num[m1][i]);
        matrix_ym[i] = (temp<< 18) | matrix_ym[i];
        temp = pgm_read_byte(&num[m2][i]);
        matrix_ym[i]= (temp<< 13) | matrix_ym[i];
        temp = pgm_read_byte(&num[d1][i]);
        matrix_ym[i] = (temp<< 3) | matrix_ym[i];
        temp = pgm_read_byte(&num[d2][i]);
        matrix_ym[i] = (temp>>2) | matrix_ym[i];        
    }
    //月份和日期之间的“-”
    matrix_ym[3] = (3<<13) | matrix_ym[3];

    //重置星期
    for(int i=0;i<8;i++)
        matrix_day[i]=0;

    //更新星期

    // for(int i=0;i<8;i++)
    // {
    //     temp = pgm_read_byte(&num[d1][i]);
    //     matrix_day[i] = (temp<<20) | matrix_day[i];
    //     temp = pgm_read_byte(&num[d2][i]);
    //     matrix_day[i] = (temp<<15) | matrix_day[i];
    //     temp = pgm_read_byte (&num[dow][i]);
    //     matrix_day[i] = (temp<<7) | matrix_day[i];
    // }
    for(int i=0;i<8;i++)
    {
        temp = pgm_read_dword (&charweeks[dow][i]);
        matrix_day[i] =temp<<4;
    }

    //更新日期和星期前的分隔符“-”

   // matrix_day[3] = (3<<29) | matrix_day[3];
   // matrix_day[3] = (3<<16) | matrix_day[3];

    
}

void MatrixClock::wifidot()
{
    unsigned long temp ;
    for(int i = 0;i<8;i++)
    {
        temp = pgm_read_dword(&charwifi[i]);
        matrix_clock[i]= temp;
    }

    for(int i=0;i<=this->dots;i++)
    {
        bitSet(matrix_clock[6],13-i);
    }
    dots++;
    if(dots>=13)
        dots=0;
    Display();
}

void MatrixClock::wificonnected()
{
    for(int i=0;i<8;i++)
        matrix_clock[i] = pgm_read_dword(&charconnected[i]);

    Display();
}

void MatrixClock::wifinotconn()
{
    for(int i=0;i<8;i++)
        matrix_clock[i] = pgm_read_dword(&charnotcon[i]);
    Display();
}